//! # Kubernetes 客户端
//!
//! 提供与 Kubernetes API 服务器交互的客户端实现。

use std::sync::Arc;
use std::time::Duration;
use async_trait::async_trait;
use kube::{Client, Config};
use tracing::{info, debug, warn};

use crate::error::{K8sError, K8sResult};

/// Kubernetes 客户端配置
#[derive(Debug, Clone)]
pub struct K8sClientConfig {
    /// API 服务器地址
    pub api_server_url: Option<String>,
    /// 认证令牌
    pub token: Option<String>,
    /// 证书路径
    pub ca_cert_path: Option<String>,
    /// 客户端证书路径
    pub client_cert_path: Option<String>,
    /// 客户端私钥路径
    pub client_key_path: Option<String>,
    /// 命名空间
    pub namespace: Option<String>,
    /// 请求超时时间
    pub timeout: Duration,
    /// 是否跳过 TLS 验证
    pub insecure_skip_tls_verify: bool,
}

impl Default for K8sClientConfig {
    fn default() -> Self {
        Self {
            api_server_url: None,
            token: None,
            ca_cert_path: None,
            client_cert_path: None,
            client_key_path: None,
            namespace: Some("default".to_string()),
            timeout: Duration::from_secs(30),
            insecure_skip_tls_verify: false,
        }
    }
}

impl K8sClientConfig {
    /// 创建新的配置
    pub fn new() -> Self {
        Self::default()
    }

    /// 设置 API 服务器地址
    pub fn with_api_server_url(mut self, url: String) -> Self {
        self.api_server_url = Some(url);
        self
    }

    /// 设置认证令牌
    pub fn with_token(mut self, token: String) -> Self {
        self.token = Some(token);
        self
    }

    /// 设置证书路径
    pub fn with_ca_cert_path(mut self, path: String) -> Self {
        self.ca_cert_path = Some(path);
        self
    }

    /// 设置命名空间
    pub fn with_namespace(mut self, namespace: String) -> Self {
        self.namespace = Some(namespace);
        self
    }

    /// 设置超时时间
    pub fn with_timeout(mut self, timeout: Duration) -> Self {
        self.timeout = timeout;
        self
    }

    /// 跳过 TLS 验证
    pub fn insecure(mut self) -> Self {
        self.insecure_skip_tls_verify = true;
        self
    }

    /// 从环境变量加载配置
    pub fn from_env() -> Self {
        let mut config = Self::default();

        if let Ok(url) = std::env::var("KUBERNETES_SERVICE_HOST") {
            let port = std::env::var("KUBERNETES_SERVICE_PORT").unwrap_or_else(|_| "443".to_string());
            config.api_server_url = Some(format!("https://{}:{}", url, port));
        }

        if let Ok(token_path) = std::env::var("KUBERNETES_SERVICE_ACCOUNT_TOKEN_PATH") {
            if let Ok(token) = std::fs::read_to_string(token_path) {
                config.token = Some(token.trim().to_string());
            }
        }

        if let Ok(ca_path) = std::env::var("KUBERNETES_SERVICE_ACCOUNT_CA_PATH") {
            config.ca_cert_path = Some(ca_path);
        }

        if let Ok(namespace) = std::env::var("KUBERNETES_NAMESPACE") {
            config.namespace = Some(namespace);
        }

        config
    }
}

/// Kubernetes 客户端
pub struct KubernetesClient {
    /// Kube 客户端
    client: Client,
    /// 配置
    config: K8sClientConfig,
}

impl KubernetesClient {
    /// 创建新的客户端（从集群内配置）
    pub async fn new() -> K8sResult<Self> {
        Self::from_cluster().await
    }

    /// 从集群内配置创建客户端
    pub async fn from_cluster() -> K8sResult<Self> {
        info!("正在创建集群内 Kubernetes 客户端");

        let config = Config::incluster()
            .map_err(|e| K8sError::config_error(format!("无法加载集群内配置: {}", e)))?;

        let client = Client::try_from(config)
            .map_err(|e| K8sError::connection_error(format!("无法创建 Kubernetes 客户端: {}", e)))?;

        let k8s_config = K8sClientConfig::from_env();

        info!("Kubernetes 客户端创建成功");
        Ok(Self {
            client,
            config: k8s_config,
        })
    }

    /// 从 kubeconfig 文件创建客户端
    pub async fn from_kubeconfig() -> K8sResult<Self> {
        info!("正在从 kubeconfig 创建 Kubernetes 客户端");

        let config = Config::infer()
            .await
            .map_err(|e| K8sError::config_error(format!("无法推断 Kubernetes 配置: {}", e)))?;

        let client = Client::try_from(config)
            .map_err(|e| K8sError::connection_error(format!("无法创建 Kubernetes 客户端: {}", e)))?;

        info!("Kubernetes 客户端创建成功");
        Ok(Self {
            client,
            config: K8sClientConfig::default(),
        })
    }

    /// 从自定义配置创建客户端
    pub async fn from_config(config: K8sClientConfig) -> K8sResult<Self> {
        info!("正在从自定义配置创建 Kubernetes 客户端");

        let mut kube_config = if let Some(url) = &config.api_server_url {
            let mut cfg = Config::new(url.parse()
                .map_err(|e| K8sError::config_error(format!("无效的 API 服务器 URL: {}", e)))?);
            
            cfg.read_timeout = Some(config.timeout);
            
            if config.insecure_skip_tls_verify {
                cfg.accept_invalid_certs = true;
            }

            if let Some(token) = &config.token {
                cfg.auth_info.token = Some(token.clone().into());
            }

            cfg
        } else {
            Config::infer()
                .await
                .map_err(|e| K8sError::config_error(format!("无法推断 Kubernetes 配置: {}", e)))?
        };

        // 设置默认命名空间
        if let Some(namespace) = &config.namespace {
            kube_config.default_namespace = namespace.clone();
        }

        let client = Client::try_from(kube_config)
            .map_err(|e| K8sError::connection_error(format!("无法创建 Kubernetes 客户端: {}", e)))?;

        info!("Kubernetes 客户端创建成功");
        Ok(Self { client, config })
    }

    /// 获取 Kube 客户端
    pub fn client(&self) -> &Client {
        &self.client
    }

    /// 获取配置
    pub fn config(&self) -> &K8sClientConfig {
        &self.config
    }

    /// 获取默认命名空间
    pub fn default_namespace(&self) -> &str {
        self.config.namespace.as_deref().unwrap_or("default")
    }

    /// 检查连接是否健康
    pub async fn health_check(&self) -> K8sResult<()> {
        debug!("执行 Kubernetes 连接健康检查");

        let version = self.client.apiserver_version().await
            .map_err(|e| K8sError::health_check_error(format!("无法获取 API 服务器版本: {}", e)))?;

        info!("Kubernetes API 服务器版本: {}", version.git_version);
        Ok(())
    }

    /// 列出可用的 API 资源
    pub async fn list_api_resources(&self) -> K8sResult<Vec<String>> {
        debug!("列出可用的 API 资源");

        // 这里可以实现更复杂的 API 资源发现逻辑
        // 暂时返回一些常用资源
        Ok(vec![
            "pods".to_string(),
            "services".to_string(),
            "deployments".to_string(),
            "configmaps".to_string(),
            "secrets".to_string(),
            "ingresses".to_string(),
        ])
    }

    /// 获取集群信息
    pub async fn get_cluster_info(&self) -> K8sResult<ClusterInfo> {
        let version = self.client.apiserver_version().await
            .map_err(|e| K8sError::connection_error(format!("无法获取集群信息: {}", e)))?;

        Ok(ClusterInfo {
            version: version.git_version,
            platform: version.platform,
        })
    }
}

/// 集群信息
#[derive(Debug, Clone)]
pub struct ClusterInfo {
    /// Kubernetes 版本
    pub version: String,
    /// 平台信息
    pub platform: String,
}

/// Kubernetes 客户端 trait
#[async_trait]
pub trait K8sClient: Send + Sync {
    /// 获取 Kube 客户端
    fn client(&self) -> &Client;

    /// 健康检查
    async fn health_check(&self) -> K8sResult<()>;

    /// 获取集群信息
    async fn get_cluster_info(&self) -> K8sResult<ClusterInfo>;
}

#[async_trait]
impl K8sClient for KubernetesClient {
    fn client(&self) -> &Client {
        &self.client
    }

    async fn health_check(&self) -> K8sResult<()> {
        self.health_check().await
    }

    async fn get_cluster_info(&self) -> K8sResult<ClusterInfo> {
        self.get_cluster_info().await
    }
}

/// 客户端工厂
pub struct K8sClientFactory;

impl K8sClientFactory {
    /// 创建客户端（自动检测环境）
    pub async fn create() -> K8sResult<Arc<KubernetesClient>> {
        // 首先尝试集群内配置
        match KubernetesClient::from_cluster().await {
            Ok(client) => {
                info!("使用集群内配置创建 Kubernetes 客户端");
                Ok(Arc::new(client))
            }
            Err(_) => {
                // 如果失败，尝试 kubeconfig
                warn!("集群内配置失败，尝试使用 kubeconfig");
                match KubernetesClient::from_kubeconfig().await {
                    Ok(client) => {
                        info!("使用 kubeconfig 创建 Kubernetes 客户端");
                        Ok(Arc::new(client))
                    }
                    Err(e) => {
                        warn!("无法创建 Kubernetes 客户端: {}", e);
                        Err(e)
                    }
                }
            }
        }
    }

    /// 从配置创建客户端
    pub async fn create_from_config(config: K8sClientConfig) -> K8sResult<Arc<KubernetesClient>> {
        let client = KubernetesClient::from_config(config).await?;
        Ok(Arc::new(client))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::time::Duration;

    #[test]
    fn test_config_builder() {
        let config = K8sClientConfig::new()
            .with_api_server_url("https://kubernetes.example.com".to_string())
            .with_namespace("my-namespace".to_string())
            .with_timeout(Duration::from_secs(60))
            .insecure();

        assert_eq!(config.api_server_url, Some("https://kubernetes.example.com".to_string()));
        assert_eq!(config.namespace, Some("my-namespace".to_string()));
        assert_eq!(config.timeout, Duration::from_secs(60));
        assert!(config.insecure_skip_tls_verify);
    }

    #[test]
    fn test_config_from_env() {
        // 这个测试需要模拟环境变量
        let config = K8sClientConfig::from_env();
        assert!(config.namespace.is_some());
    }

    #[tokio::test]
    async fn test_client_creation_fails_gracefully() {
        // 这个测试应该失败，因为没有真实的 K8s 集群
        let result = KubernetesClient::from_cluster().await;
        assert!(result.is_err());
    }
}